use crate::mem::phys_to_virt;
use aarch64_cpu::asm;
use memory_addr::PhysAddr;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use tock_registers::registers::ReadWrite;

pub use super::regs::*;
pub use super::types::*;

impl PwmController {
    pub fn new(base_addr: usize) -> Self {
        info!("PWM base address: {:x}", base_addr);
        Self {
            base: base_addr,
            channels: [
                PwmChannel {
                    config: None,
                    enabled: false,
                },
                PwmChannel {
                    config: None,
                    enabled: false,
                },
            ],
        }
    }

    fn registers(&self) -> &PwmRegisters {
        let reg_phys_addr = PhysAddr::from(self.base);
        let reg_virt_addr = phys_to_virt(reg_phys_addr);
        unsafe { &*(reg_virt_addr.as_ptr() as *const PwmRegisters) }
    }

    fn get_channel_reg(&self, channel: usize) -> ChannelRegisters<'_> {
        let regs = self.registers();
        // 根据飞腾SDK的寄存器布局计算通道寄存器地址
        let channel_base = FPWM_N(channel + 1); // 通道1对应0x400偏移，通道2对应0x800偏移

        ChannelRegisters {
            tim_cnt: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x00)
                    as *const ReadWrite<u32, TIM_CNT::Register>)
            },
            tim_ctrl: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x04)
                    as *const ReadWrite<u32, TIM_CTRL::Register>)
            },
            state: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x08)
                    as *const ReadWrite<u32, STATE::Register>)
            },
            pwm_period: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x0C)
                    as *const ReadWrite<u32, PWM_PERIOD::Register>)
            },
            pwm_ctrl: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x10)
                    as *const ReadWrite<u32, PWM_CTRL::Register>)
            },
            pwm_ccr: unsafe {
                &*((regs as *const _ as usize + channel_base + 0x14)
                    as *const ReadWrite<u32, PWM_CCR::Register>)
            },
        }
    }

    pub fn configure_channel(
        &mut self,
        channel: usize,
        config: PwmConfig,
    ) -> Result<(), &'static str> {
        info!("Configuring PWM channel {}", channel);
        if channel >= CHANNELS_PER_CONTROLLER {
            return Err("Invalid channel number");
        }

        // 禁用通道
        self.disable_channel(channel);

        // 保存配置
        self.channels[channel].config = Some(config);
        Ok(())
    }

    pub fn enable_channel(&mut self, channel: usize) -> Result<(), &'static str> {
        info!("Enabling PWM channel {}", channel);
        if channel >= CHANNELS_PER_CONTROLLER {
            return Err("Invalid channel number");
        }

        // 确保通道已正确配置
        if self.channels[channel].config.is_none() {
            return Err("Channel not configured");
        }

        // 重置通道
        {
            let ch_reg = self.get_channel_reg(channel);
            ch_reg.tim_ctrl.modify(TIM_CTRL::SW_RST::ResetActive);
            while ch_reg.tim_ctrl.read(TIM_CTRL::SW_RST) == 1 {
                asm::nop();
            }
        }

        // 禁用通道
        self.disable_channel(channel);

        let ch_reg = self.get_channel_reg(channel);
        let config = self.channels[channel].config.unwrap();

        // 设置参数
        let period = SYSTEM_CLK / config.frequency; // C代码中divider是50MHz/10000Hz = 5000，但实际寄存器值是499
        let divider = period - 1; // C代码中divider是period-1
        let duty = (period as f32 * config.duty_cycle) as u32;

        info!("Period: {}, Duty: {}", period, duty);
        info!("Counting mode: {}", config.counting_mode);
        info!("Output behavior: {}", config.output_behavior);
        info!("FIFO mode: {}", config.use_fifo);

        // 打印寄存器地址和值
        let tim_ctrl_addr = ch_reg.tim_ctrl as *const _ as usize;
        let pwm_period_addr = ch_reg.pwm_period as *const _ as usize;
        let pwm_ctrl_addr = ch_reg.pwm_ctrl as *const _ as usize;
        let pwm_ccr_addr = ch_reg.pwm_ccr as *const _ as usize;

        info!("TIM_CTRL register address: 0x{:x}", tim_ctrl_addr);
        info!("PWM_PERIOD register address: 0x{:x}", pwm_period_addr);
        info!("PWM_CTRL register address: 0x{:x}", pwm_ctrl_addr);
        info!("PWM_CCR register address: 0x{:x}", pwm_ccr_addr);

        // 设置计数模式
        ch_reg
            .tim_ctrl
            .modify(TIM_CTRL::MODE.val(config.counting_mode));
        info!("Setting timer control mode: {}", config.counting_mode);

        // 设置分频器
        ch_reg.tim_ctrl.modify(TIM_CTRL::DIV.val(divider));
        info!("Setting divider: {}", divider);

        // 设置周期
        ch_reg.pwm_period.write(PWM_PERIOD::CCR.val(period));
        info!("Setting period: {}", period);

        // 设置PWM控制模式
        ch_reg.pwm_ctrl.modify(PWM_CTRL::MODE::Compare);
        info!("Setting PWM control mode");

        // 设置极性
        ch_reg
            .pwm_ctrl
            .modify(PWM_CTRL::CMP.val(config.output_behavior));
        info!("Setting polarity: {}", config.output_behavior);

        // 设置占空比源（FIFO或寄存器）
        ch_reg.pwm_ctrl.modify(PWM_CTRL::DUTY_SEL::Register_);
        info!("Setting duty source: Register");

        // 设置脉冲宽度
        let state_val = ch_reg.state.get();
        info!("Read STATE register: 0x{:x}", state_val);

        let ccr_val = ch_reg.pwm_ccr.get();
        info!("Read CCR before setting pulse: 0x{:x}", ccr_val);

        ch_reg.pwm_ccr.write(PWM_CCR::CCR.val(duty));
        info!("Writing CCR with pulse value: 0x{:x}", duty);

        // 启用通道
        let current_tim_ctrl = ch_reg.tim_ctrl.get();
        info!("Read TIM_CTRL before enable: 0x{:x}", current_tim_ctrl);

        ch_reg.tim_ctrl.modify(TIM_CTRL::ENABLE::Enabled);
        let new_tim_ctrl = ch_reg.tim_ctrl.get();
        info!("Writing TIM_CTRL with enable bit: 0x{:x}", new_tim_ctrl);

        self.channels[channel].enabled = true;
        Ok(())
    }

    pub fn disable_channel(&mut self, channel: usize) {
        info!("Disabling PWM channel {}", channel);
        let ch_reg = self.get_channel_reg(channel);
        let current_tim_ctrl = ch_reg.tim_ctrl.get();
        info!("Read TIM_CTRL before disable: 0x{:x}", current_tim_ctrl);

        ch_reg.tim_ctrl.modify(TIM_CTRL::ENABLE::Disabled);
        let new_tim_ctrl = ch_reg.tim_ctrl.get();
        info!("Writing TIM_CTRL with disable bit: 0x{:x}", new_tim_ctrl);
        self.channels[channel].enabled = false;
    }

    pub fn safe_stop_channel(&mut self, channel: usize) -> Result<(), &'static str> {
        info!("Safe stopping PWM channel {}", channel);
        let ch_reg = self.get_channel_reg(channel);
        ch_reg.pwm_ccr.write(PWM_CCR::CCR.val(0));
        while ch_reg.tim_cnt.read(TIM_CNT::CNT) != 0 {
            asm::nop();
        }
        self.disable_channel(channel);
        Ok(())
    }
}

struct ChannelRegisters<'a> {
    tim_cnt: &'a ReadWrite<u32, TIM_CNT::Register>,
    tim_ctrl: &'a ReadWrite<u32, TIM_CTRL::Register>,
    state: &'a ReadWrite<u32, STATE::Register>,
    pwm_period: &'a ReadWrite<u32, PWM_PERIOD::Register>,
    pwm_ctrl: &'a ReadWrite<u32, PWM_CTRL::Register>,
    pwm_ccr: &'a ReadWrite<u32, PWM_CCR::Register>,
}

impl PwmSystem {
    pub fn new() -> Self {
        // 根据飞腾SDK中的定义，FPWM_BASE_ADDR = 0x2804A000
        // 每个控制器间隔0x1000字节
        const FPWM_BASE_ADDR: usize = 0x2804A000;
        const CONTROLLER_BASES: [usize; PWM_CONTROLLERS] = [
            FPWM_BASE_ADDR + (0 << 12), // FPWM0: 0x2804A000
            FPWM_BASE_ADDR + (1 << 12), // FPWM1: 0x2804B000
            FPWM_BASE_ADDR + (2 << 12), // FPWM2: 0x2804C000
            FPWM_BASE_ADDR + (3 << 12), // FPWM3: 0x2804D000
            FPWM_BASE_ADDR + (4 << 12), // FPWM4: 0x2804E000
            FPWM_BASE_ADDR + (5 << 12), // FPWM5: 0x2804F000
            FPWM_BASE_ADDR + (6 << 12), // FPWM6: 0x28050000
            FPWM_BASE_ADDR + (7 << 12), // FPWM7: 0x28051000
        ];
        let controllers = CONTROLLER_BASES.map(|base| PwmController::new(base));
        Self { controllers }
    }

    pub fn global_enable(&self) {
        info!("Enabling PWM globally");
        let mut enable_mask: u32 = 0;
        for (i, ctrl) in self.controllers.iter().enumerate() {
            if ctrl.channels.iter().any(|ch| ch.config.is_some()) {
                enable_mask |= 1 << i;
            }
        }
        info!("Enable mask: {:x}", enable_mask);

        // 使用phys_to_virt进行地址转换后再访问寄存器
        let reg_phys_addr = PhysAddr::from(GLOBAL_ENABLE_REG_ADDR);
        let reg_virt_addr = phys_to_virt(reg_phys_addr);
        info!(
            "Global enable register physical address: 0x{:x}",
            GLOBAL_ENABLE_REG_ADDR
        );
        info!(
            "Global enable register virtual address: 0x{:x}",
            reg_virt_addr
        );
        unsafe {
            let reg_ptr = reg_virt_addr.as_mut_ptr() as *mut u32;
            info!(
                "Writing enable mask 0x{:x} to global enable register at virtual address 0x{:x} (physical address 0x{:x})",
                enable_mask, reg_virt_addr, GLOBAL_ENABLE_REG_ADDR
            );
            reg_ptr.write_volatile(enable_mask);
            let read_back = reg_ptr.read_volatile();
            info!(
                "Read back value from global enable register: 0x{:x}",
                read_back
            );
        }
    }

    pub fn controller(&mut self, index: usize) -> Option<&mut PwmController> {
        info!("Getting PWM controller {}", index);
        if index < PWM_CONTROLLERS {
            Some(&mut self.controllers[index])
        } else {
            None
        }
    }
}
